//
//  ReversiController.m
//  Reversi
//	
//  Created by 成瀬 龍人 on 2/4/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "ReversiController.h"
#import "ReversiBoard.h"
#include <mach/mach_time.h>

@implementation ReversiController

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)application{
	return YES;
}

- (void)applicationDidFinishLaunching:(NSNotification*)notification{
	[self openInitializeWindow:self];
}

- (void)put:(ReversiBoardPosition*)pos{
	[self performSelector:putStoneInCurrentState withObject:pos];
}

- (void)pass{
	NSObject<ReversiPlaying>* nextPlayer = (currentPlayerStone == REVERSI_STONE_BLACK) ?  secondPlayer : firstPlayer;
	ReversiStone nextPlayerStone = (currentPlayerStone == REVERSI_STONE_BLACK) ?  REVERSI_STONE_WHITE : REVERSI_STONE_BLACK;
	[boardView changePlayerTo:nextPlayer 
					  toStone:nextPlayerStone 
				   fromPlayer:currentPlayer 
					fromStone:currentPlayerStone];
	currentPlayer = nextPlayer;
	currentPlayerStone = nextPlayerStone;
	putStoneInCurrentState = @selector(_putStoneInSelectStonePositionState:);
}

- (IBAction)openInitializeWindow:(id)sender{
	[[NSApplication sharedApplication]
	 beginSheet:initializePanel modalForWindow:reversiWindow modalDelegate:self didEndSelector:nil contextInfo:nil];
}

- (void)initReversi:(NSObject<ReversiBoardView>*)view:(NSObject<ReversiPlaying>*)aFirstPlayer:(NSObject<ReversiPlaying>*)aSecondPlayer{
	board = [[ReversiBoard alloc] initForGame];
	boardView = view;
	[boardView initWithBoard:board
				  controller:self
				 blackPlayer:aFirstPlayer
				 whitePlayer:aSecondPlayer];
	firstPlayer = aFirstPlayer;
	secondPlayer = aSecondPlayer;
	currentPlayer = firstPlayer;
	currentPlayerStone = REVERSI_STONE_BLACK;
	putStoneInCurrentState = @selector(_putStoneInSelectStonePositionState:);	
	NSLog(@"initialize board");
}

- (void)_putStoneInSelectStonePositionState:(ReversiBoardPosition*)pos{
	//次の手を選択
	if (![currentPlayer isKindOfClass:[ReversiPlayer class]]){
		pos = [currentPlayer nextHand:currentPlayerStone :board];
	}
	
	//選択した手を置けなかった場合は、何もせず状態はそのまま
	if (nil == pos || ![board isPutOK: currentPlayerStone: pos]){
		[boardView startInvalidPutPosAnimation:currentPlayerStone:currentPlayer];
		NSTimer* timer = [NSTimer timerWithTimeInterval:[boardView timerInterval]
												 target:self
											   selector:@selector(_updateInvalidPutPosAnimation:)
											   userInfo:nil
												repeats:true];
		[[NSRunLoop currentRunLoop] addTimer:timer
									 forMode:NSDefaultRunLoopMode];
		putStoneInCurrentState = @selector(_putStoneInAnimationState:);
		NSLog(@"not put!");
		NSLog(@"change to select stone state.");
		return ;
	}
	//置ける場合は、石を返してアニメーションを開始
	else {
		[boardView startPutAnimation:currentPlayerStone:pos:[board putAndChangeEx:currentPlayerStone:pos]];
		NSTimer* timer = [NSTimer timerWithTimeInterval:[boardView timerInterval]
												 target:self
											   selector:@selector(_updatePutAnimation:)
											   userInfo:nil
												repeats:true];
		[[NSRunLoop currentRunLoop] addTimer:timer
									 forMode:NSDefaultRunLoopMode];
		putStoneInCurrentState = @selector(_putStoneInAnimationState:);
		return ;
	}
}

- (void)_putStoneInAnimationState:(ReversiBoardPosition*)pos{
	//アニメーション中にボタンが押されても何もしない
	NSLog(@"call in animation.");
}

- (void)_updateInvalidPutPosAnimation:(NSTimer*)timer{
	if (NO == [boardView updateInvalidPutPosAnimation]){
		[boardView changePlayerTo:currentPlayer 
						  toStone:currentPlayerStone 
					   fromPlayer:currentPlayer 
						fromStone:currentPlayerStone];
		putStoneInCurrentState = @selector(_putStoneInSelectStonePositionState:);
		[timer invalidate];
	}
}

- (void)_updatePassAnimation:(NSTimer*)timer{
	if (NO == [boardView updatePassAnimation]){
		NSObject<ReversiPlaying>* nextPlayer = (currentPlayerStone == REVERSI_STONE_BLACK) ?  secondPlayer : firstPlayer;
		ReversiStone nextPlayerStone = (currentPlayerStone == REVERSI_STONE_BLACK) ?  REVERSI_STONE_WHITE : REVERSI_STONE_BLACK;
		[boardView changeToPassState:nextPlayer:nextPlayerStone];
		currentPlayer = nextPlayer;
		currentPlayerStone = nextPlayerStone;
		putStoneInCurrentState = @selector(_putStoneInPassState:);		
		[timer invalidate];
	}
}

- (void)_updatePutAnimation:(NSTimer*)timer{
	if (NO == [boardView updatePutAnimation]){
		NSObject<ReversiPlaying>* nextPlayer = (currentPlayerStone == REVERSI_STONE_BLACK) ?  secondPlayer : firstPlayer;
		ReversiStone nextPlayerStone = (currentPlayerStone == REVERSI_STONE_BLACK) ?  REVERSI_STONE_WHITE : REVERSI_STONE_BLACK;
		//ゲームオーバーだったらゲームオーバー画面をだす
		if ([board isGameOver]){
			[[NSApplication sharedApplication]
			 beginSheet:gameResultPanel modalForWindow:reversiWindow modalDelegate:self didEndSelector:nil contextInfo:nil];
		}
		//次のプレイヤーが置く場所が無ければパス状態へ
		else if(0 == [board allocatablePositionsNum:nextPlayerStone]){
			[boardView startPassAnimation:nextPlayerStone:nextPlayer];
			NSTimer* timer = [NSTimer timerWithTimeInterval:[boardView timerInterval]
													 target:self
												   selector:@selector(_updatePassAnimation:)
												   userInfo:nil
													repeats:true];
			[[NSRunLoop currentRunLoop] addTimer:timer
										 forMode:NSDefaultRunLoopMode];			
		}
		//アニメーションを終了し、次のプレイヤーへ制御を渡す
		else {
			[boardView changePlayerTo:nextPlayer 
							  toStone:nextPlayerStone 
						   fromPlayer:currentPlayer 
							fromStone:currentPlayerStone];
			currentPlayer = nextPlayer;
			currentPlayerStone = nextPlayerStone;
			putStoneInCurrentState = @selector(_putStoneInSelectStonePositionState:);
		}
		[timer invalidate];
	}
}

- (bool)isBlackWin{
	return [board numberOf:REVERSI_STONE_BLACK] > [board numberOf:REVERSI_STONE_WHITE];
}

- (bool)isWhiteWin{
	return [board numberOf:REVERSI_STONE_BLACK] < [board numberOf:REVERSI_STONE_WHITE];
}

- (bool)isDraw{
	return [board numberOf:REVERSI_STONE_BLACK] == [board numberOf:REVERSI_STONE_WHITE];
}

@end
